home *** CD-ROM | disk | FTP | other *** search
/ Scene Storm / Scene Storm - Volume 1.iso / coding / c / unix / src / signals.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-29  |  3.8 KB  |  204 lines

  1. #include "amiga.h"
  2. #include "timers.h"
  3. #include "signals.h"
  4. #include "processes.h"
  5.  
  6. static ULONG signalsigs;    /* When one of these occur, call handle_signals */
  7. void (*_sig_handlers[NSIG])(int);
  8. long _sig_mask, _sig_pending;
  9.  
  10. /* Alarm signal */
  11. /* ------------ */
  12.  
  13. static struct timeinfo *alarm_timer;
  14.  
  15. static int check_alarm(ULONG sigs)
  16. {
  17.   return alarm_timer && _timer_expired(alarm_timer);
  18. }
  19.  
  20. void alarm(int secs)
  21. /* Effect: Schedule a SIGALRM after secs seconds
  22. */
  23. {
  24.   _timer_start(alarm_timer, secs, 0);
  25. }
  26.  
  27. static void init_alarm(void)
  28. {
  29.   if (!(alarm_timer = _alloc_timer())) _fail("Failed to create timer");
  30.   signalsigs |= _timer_sig(alarm_timer);
  31. }
  32.  
  33. static void cleanup_alarm(void)
  34. {
  35.   _free_timer(alarm_timer);
  36. }
  37.  
  38. /* SIGINT definition */
  39. /* ----------------- */
  40.  
  41. static void init_sigint(void)
  42. {
  43.   signalsigs |= SIGBREAKF_CTRL_C;
  44. }
  45.  
  46. /*static void cleanup_sigint(void) { }*/
  47.  
  48. static int check_sigint(ULONG sigs)
  49. {
  50.   return (sigs & SIGBREAKF_CTRL_C) != 0;
  51. }
  52.  
  53. /* SIGQUIT definition */
  54. /* ------------------ */
  55.  
  56. static void init_sigquit(void)
  57. {
  58.   signalsigs |= SIGBREAKF_CTRL_D;
  59. }
  60.  
  61. /*static void cleanup_sigquit(void) { }*/
  62.  
  63. static int check_sigquit(ULONG sigs)
  64. {
  65.   return (sigs & SIGBREAKF_CTRL_D) != 0;
  66. }
  67.  
  68. /* SIGCHLD definition */
  69. /* ------------------ */
  70.  
  71. static void init_children(void)
  72. {
  73.   _init_processes();
  74.   signalsigs |= 1L << _children_exit->mp_SigBit;
  75. }
  76.  
  77. static void cleanup_children(void)
  78. {
  79.   _cleanup_processes();
  80. }
  81.  
  82. static int check_children(ULONG sigs)
  83. {
  84.   struct exit_message *msg;
  85.   int change = FALSE;
  86.   
  87.   while (msg = (struct exit_message *)GetMsg(_children_exit))
  88.     {
  89.       struct process *p;
  90.  
  91.       if ((p = _find_pid(msg->pid)) && p->status == alive)
  92.     {
  93.       change = TRUE;
  94.       p->status = exited;
  95.       p->rc = msg->rc;
  96.     }
  97.       FreeMem(msg, sizeof(struct exit_message));
  98.     }
  99.   return change;
  100. }
  101.  
  102. /* Signal dispatching */
  103. /* ------------------ */
  104.  
  105. void _sig_dispatch(int sig)
  106. /* Effect: Do the action associated with signal sig it it isn't masked
  107.      Mask it for the duration of the signal exec
  108. */
  109. {
  110.   void (*fn)(int);
  111.   int smask = 1 << sig;
  112.  
  113.   if (sig == SIGKILL) _exit(0);
  114.  
  115.   if (_sig_mask & smask) _sig_pending |= smask;
  116.   else
  117.     do
  118.       {
  119.     _sig_pending &= ~smask;
  120.     if (sig >= 0 && sig < NSIG)
  121.       {
  122.         fn = _sig_handlers[sig];
  123.  
  124.         if (fn == SIG_DFL)
  125.           switch (sig)
  126.         {
  127.         case SIGCHLD: case SIGURG: case SIGWINCH: break;
  128.         case SIGINT: case SIGQUIT: _message("user interrupt");
  129.         default: _exit(0);
  130.         }
  131.         else if (fn != SIG_IGN)
  132.           {
  133.         _sig_mask |= smask;
  134.         _sig_handlers[sig](sig);
  135.         _sig_mask &= ~smask;
  136.           }
  137.       }
  138.       }
  139.     while (_sig_pending & smask); /* Signal may have been generated during the
  140.                      signal handling function. */
  141. }
  142.  
  143. ULONG _check_signals(ULONG extra_sigs)
  144. {
  145.   return SetSignal(0, signalsigs | extra_sigs);
  146. }
  147.  
  148. ULONG _wait_signals(ULONG extra_sigs)
  149. {
  150.   return Wait(signalsigs | extra_sigs);
  151. }
  152.  
  153. int _handle_signals(ULONG sigs)
  154. {
  155.   int signaled = 0;
  156.  
  157.   if (check_alarm(sigs)) { signaled = 1; _sig_dispatch(SIGALRM); }
  158.   if (check_sigint(sigs)) { signaled = 1; _sig_dispatch(SIGINT); }
  159.   if (check_sigquit(sigs)) { signaled = 1; _sig_dispatch(SIGQUIT); }
  160.   if (check_children(sigs)) { signaled = 1; _sig_dispatch(SIGCHLD); }
  161.  
  162.   return signaled;
  163. }
  164.  
  165. /* Patch into SAS signal stuff so as to replace it */
  166.  
  167. void CXFERR(int code)
  168. {
  169.     extern int _FPERR;
  170.  
  171.     _FPERR = code;
  172.     _sig_dispatch(SIGFPE);
  173. }
  174.  
  175. void chkabort(void)
  176. /* Checks all signals */
  177. {
  178.   _handle_signals(_check_signals(0));
  179. }
  180.  
  181. void Chk_Abort(void) { chkabort(); }
  182.  
  183. /* Initialisation */
  184. /* -------------- */
  185.  
  186. void _init_signals(void)
  187. {
  188.   int i;
  189.  
  190.   for (i = 0; i < NSIG; i++) _sig_handlers[i] = SIG_DFL;
  191.   _sig_mask = _sig_pending = 0;
  192.   signalsigs = 0;
  193.  
  194.   init_sigint(); init_sigquit(); init_alarm(); init_children();
  195. }
  196.  
  197. void _cleanup_signals(void)
  198. {
  199.   cleanup_alarm();
  200.   /*cleanup_sigquit();*/
  201.   /*cleanup_sigint();*/
  202.   cleanup_children();
  203. }
  204.